package cn.fintecher.gis.service;

import cn.fintecher.gis.entity.*;
import cn.fintecher.gis.enums.*;
import cn.fintecher.gis.exception.BadRequestException;
import cn.fintecher.gis.model.WebSocketMessageModel;
import cn.fintecher.gis.model.request.FlowApplyRequest;
import cn.fintecher.gis.model.request.FlowApproveRequest;
import cn.fintecher.gis.model.request.FlowBusinessRequest;
import cn.fintecher.gis.model.request.FlowNextUserRequest;
import cn.fintecher.gis.model.response.*;
import cn.fintecher.gis.model.session.SessionModel;
import cn.fintecher.gis.respository.*;
import cn.fintecher.gis.utils.BeanUtils;
import com.google.common.collect.Lists;
import com.querydsl.core.BooleanBuilder;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service("flowService")
public class FlowService {

    private final Logger log = LoggerFactory.getLogger(FlowService.class);

    @Autowired
    private FlowInfoRepository flowInfoRepository;

    @Autowired
    private FlowHistoryRepository flowHistoryRepository;

    @Autowired
    private OperatorRepository operatorRepository;

    @Autowired
    private ReportInfoRepository reportInfoRepository;

    @Autowired
    private ReportFileRepository reportFileRepository;

    @Autowired
    private GrantInfoRepository grantInfoRepository;

    @Autowired
    private GrantFileRepository grantFileRepository;

    @Autowired
    private ExpropriationRepository expropriationRepository;

    @Autowired
    private ExpropriationFileRepository expropriationFileRepository;

    @Autowired
    private SupplyInfoRepository supplyInfoRepository;

    @Autowired
    private SupplyFileRepository supplyFileRepository;

    @Autowired
    private RestsInfoRepository restsInfoRepository;

    @Autowired
    private RestsFileRepository restsFileRepository;

    @Autowired
    private UploadFileRepository uploadFileRepository;

    @Autowired
    private WebSocketService webSocketService;



    /**
     * 流程申请
     *
     * @param request
     */
    public void flowApply(FlowApplyRequest request, MessageType messageType) {
        FlowInfo flowInfo = new FlowInfo();
        flowInfo.setType(request.getType());//类型
        flowInfo.setApplyId(request.getApplyId());//业务申请id
        flowInfo.setApplyTime(new Date());//申请时间
        flowInfo.setWhether(request.getWhether());
        Optional<Operator> optional = operatorRepository.findById(request.getApplyUserId());//
        flowInfo.setApplyUser(optional.get());//申请人
        if (request.getWhether().equals(CommonShow.YES)) {
            Optional<Operator> nextOptional = operatorRepository.findById(request.getNextUserId());//
            flowInfo.setNextUser(nextOptional.get());
            flowInfo.setFlowStatus(FlowStatus.FOUND);//创建
        } else {
            flowInfo.setFlowStatus(FlowStatus.FINSH);//完成
            flowInfo.setEndTime(new Date());
        }
        flowInfo = flowInfoRepository.save(flowInfo);

        FlowHistory flowHistory = new FlowHistory();
        flowHistory.setFlowId(flowInfo.getId());
        flowHistory.setStatus(FlowResultStatus.FOUND);//申请时默认同意
        flowHistory.setTime(new Date());
        flowHistory.setUser(flowInfo.getApplyUser());
        if (request.getWhether().equals(CommonShow.NO)) {
            flowHistory.setOpinion("该业务不开启流程");
        }
        flowHistoryRepository.save(flowHistory);

        if (request.getWhether().equals(CommonShow.YES)) {
            WebSocketMessageModel model = new WebSocketMessageModel();
            model.setContent(flowInfo.getNextUser().getUsername() + ":你有一条业务需要审批！");
            model.setTitle("业务审批");
            model.setMsgDate(new Date());
            model.setMessageType(messageType);
            webSocketService.sendMessage(flowInfo.getNextUser().getUsername(), model);
        }
    }

    /**
     * 流程审批
     */
    public void flowApproval(FlowApproveRequest request) {
        Optional<FlowInfo> optional = flowInfoRepository.findById(request.getFlowId());
        if (!optional.isPresent()) {
            log.error("流程信息不存在");
        }
        FlowInfo flowInfo = optional.get();
        if (request.getStatus().equals(ApprovalStatus.AGREE)) {
            flowInfo.setFlowStatus(FlowStatus.COMPLETE_APPROVAL);//已审批
        } else {
            flowInfo.setFlowStatus(FlowStatus.REPULSE);//已审批
        }
        flowInfo = flowInfoRepository.save(flowInfo);
        FlowHistory flowHistory = new FlowHistory();
        flowHistory.setFlowId(flowInfo.getId());
        if (request.getStatus().equals(ApprovalStatus.AGREE)) {
            flowHistory.setStatus(FlowResultStatus.AGREE);
        } else {
            flowHistory.setStatus(FlowResultStatus.REFUSE);
        }
        flowHistory.setTime(new Date());
        flowHistory.setUser(flowInfo.getNextUser());
        flowHistory.setOpinion(request.getOpinion());
        flowHistoryRepository.save(flowHistory);

        WebSocketMessageModel model = new WebSocketMessageModel();
        model.setContent(flowInfo.getApplyUser().getUsername() + ":你有一条业务审批待办！");
        model.setTitle("业务审批");
        model.setMsgDate(new Date());
        setMessageType(flowInfo.getType(), model);
        webSocketService.sendMessage(flowInfo.getApplyUser().getUsername(), model);
    }


    private void setMessageType(FlowType type, WebSocketMessageModel model) {
        switch (type) {
            case REPORT:
                model.setMessageType(MessageType.REPORT);
                break;
            case EXPROPRIA:
                model.setMessageType(MessageType.EXPROPRIA);
                break;
            case GRANT:
                model.setMessageType(MessageType.GRANT);
                break;
            case SUPPLY:
                model.setMessageType(MessageType.SUPPLY);
                break;
            case RESTS:
                model.setMessageType(MessageType.RESTS);
                break;
            default:
                break;
        }
    }


    /**
     * 指定下一个审批人
     *
     * @param request
     */
    public void setFlowNextUser(FlowNextUserRequest request, SessionModel sessionModel) {
        if (request.getNextUserId().equals(sessionModel.getId())) {
            log.error("下一级审批人不能是自己");
            new BadRequestException("flowInfo", "designator.can.not.be.himself");
        }
        Optional<FlowInfo> optional = flowInfoRepository.findById(request.getFlowId());
        if (!optional.isPresent()) {
            log.error("流程信息不存在");
        }
        FlowInfo flowInfo = optional.get();
        Optional<Operator> optionalOperator = operatorRepository.findById(request.getNextUserId());//
        if (!optionalOperator.isPresent()) {
            log.error("指定的下一个审批人信息不存在");
        }
        Operator operator = optionalOperator.get();
        flowInfo.setNextUser(operator);
        flowInfo.setFlowStatus(FlowStatus.PENDING_APPROVAL);//待审批
        flowInfoRepository.save(flowInfo);

        WebSocketMessageModel model = new WebSocketMessageModel();
        model.setContent(operator.getUsername() + ":你有一条业务审批待办！");
        model.setTitle("业务审批");
        model.setMsgDate(new Date());
        setMessageType(flowInfo.getType(), model);
        webSocketService.sendMessage(flowInfo.getNextUser().getUsername(), model);
    }

    /**
     * 流程的结束
     *
     * @param flowId
     */
    public void finishFlow(String flowId) {
        Optional<FlowInfo> optional = flowInfoRepository.findById(flowId);
        if (!optional.isPresent()) {
            log.error("流程信息不存在");
        }
        FlowInfo flowInfo = optional.get();
        flowInfo.setFlowStatus(FlowStatus.FINSH);//流程结束
        flowInfo.setEndTime(new Date());//流程结束时间
        flowInfoRepository.save(flowInfo);
    }

    /**
     * 获取流程图
     *
     * @param flowId
     */
    public List<FlowChartResponse> getFlowChart(String flowId) {
        List<FlowChartResponse> list = new ArrayList<>();

        Sort sort = new Sort(Sort.Direction.ASC, "time");
        Pageable pageable = new PageRequest(0, 20, sort);
        BooleanBuilder build = new BooleanBuilder();
        build.and(QFlowHistory.flowHistory.flowId.eq(flowId));
        Iterator<FlowHistory> iterator = flowHistoryRepository.findAll(build, pageable).iterator();
        while (iterator.hasNext()) {
            FlowHistory flowHistory = iterator.next();
            FlowChartResponse response = new FlowChartResponse();
            if (flowHistory.getStatus().equals(FlowResultStatus.AGREE)) {
                response.setStatus(FlowChartStatus.AGREE);
            } else if (flowHistory.getStatus().equals(FlowResultStatus.FOUND)) {
                response.setStatus(FlowChartStatus.FOUND);
            } else {
                response.setStatus(FlowChartStatus.REFUSE);//拒绝
            }
            response.setOpinion(flowHistory.getOpinion());//审批意见
            response.setUserId(flowHistory.getUser().getId());//审批人id
            response.setUserName(flowHistory.getUser().getUsername());//审批人姓名
            response.setTime(flowHistory.getTime());
            list.add(response);
        }

        flowInfoRepository.findById(flowId).ifPresent(flowInfo -> {
            if (flowInfo.getFlowStatus().equals(FlowStatus.PENDING_APPROVAL)
                    || flowInfo.getFlowStatus().equals(FlowStatus.FOUND)) {
                FlowChartResponse response = new FlowChartResponse();
                response.setUserId(flowInfo.getNextUser().getId());//审批人id
                response.setUserName(flowInfo.getNextUser().getUsername());//审批人姓名
                response.setStatus(FlowChartStatus.PENDING_APPROVAL);//待审批
                list.add(response);
            }
            return;
        });
        return list;
    }

    /**
     * 查询当前登录人名下的业务
     *
     * @param request
     * @param sessionModel
     * @return
     */
    public List<FlowBusinessResponse> getFlowBusiness(FlowBusinessRequest request, SessionModel sessionModel) {
        List<FlowInfo> list = new ArrayList<>();
        if (request.getStatus().equals(FlowStatus.FOUND)
                || request.getStatus().equals(FlowStatus.PENDING_APPROVAL)) { //新建或者待审批
            list = getFlowBusinessPending(request, sessionModel);
        } else { //包含 已审批、打回
            list = getFlowBusinessFinish(request, sessionModel);
        }
        List<FlowBusinessResponse> responseList = new ArrayList<>();
        for (FlowInfo flowInfo : list) {
            FlowBusinessResponse response = new FlowBusinessResponse();
            response.setCreateTime(flowInfo.getApplyTime());
            response.setFlowId(flowInfo.getId());
            response.setType(flowInfo.getType());
            response.setWhether(flowInfo.getWhether());
            response.setFlowStatus(request.getStatus());
            getProjectName(flowInfo, response);
            responseList.add(response);
        }
        List<FlowBusinessResponse> responses = filterList(request, responseList);
        return responses;
    }

    /**
     * 进行条件过滤
     *
     * @param request
     * @param list
     */
    public List<FlowBusinessResponse> filterList(FlowBusinessRequest request, List<FlowBusinessResponse> list) {
        List<FlowBusinessResponse> names = new ArrayList<>();
        if (StringUtils.isNotEmpty(request.getName())) {
            names = list.stream().filter(response -> response.getName().contains(request.getName())).collect(Collectors.toList());
        } else {
            names.addAll(list);
        }

        List<FlowBusinessResponse> areaList = new ArrayList<>();
        if (request.getAreaMax() != null && request.getAreaMin() != null) {
            areaList = names.stream().filter(response -> response.getSurplusAcreage().compareTo(request.getAreaMin()) > -1
                    && response.getAcreage().compareTo(request.getAreaMax()) < 1).collect(Collectors.toList());
        } else if (request.getAreaMax() == null && request.getAreaMin() != null) {
            areaList = names.stream().filter(response -> response.getSurplusAcreage().compareTo(request.getAreaMin()) > -1).collect(Collectors.toList());
        }else if (request.getAreaMax() != null && request.getAreaMin() == null){
            areaList = names.stream().filter(response -> response.getAcreage().compareTo(request.getAreaMax()) < 1).collect(Collectors.toList());
        }else{
            areaList.addAll(names);
        }

        List<FlowBusinessResponse> regionList = new ArrayList<>();
        if (StringUtils.isNotEmpty(request.getRegion())) {
            regionList = areaList.stream().filter(response -> response.getRegions().contains(request.getRegion())).collect(Collectors.toList());
        } else {
            regionList.addAll(areaList);
        }

        return regionList;
    }

    /**
     * 获取归档数据
     *
     * @return
     */
    public List<FlowBusinessResponse> getFlowBusinessResponseFinish(FlowBusinessRequest request) {
        List<FlowBusinessResponse> list = new ArrayList<>();
        BooleanBuilder builder = new BooleanBuilder();
        QFlowInfo qFlowInfo = QFlowInfo.flowInfo;
        if (Objects.nonNull(request.getType())) {
            builder.and(qFlowInfo.type.eq(request.getType()));
        }
        builder.and(qFlowInfo.flowStatus.eq(FlowStatus.FINSH));
        Sort sort = new Sort(Sort.Direction.DESC,"applyTime");
        Iterator<FlowInfo> infoIterator = flowInfoRepository.findAll(builder,sort).iterator();
        while (infoIterator.hasNext()) {
            FlowInfo flowInfo = infoIterator.next();
            FlowBusinessResponse response = new FlowBusinessResponse();
            response.setCreateTime(flowInfo.getApplyTime());
            response.setFlowId(flowInfo.getId());
            response.setType(flowInfo.getType());
            response.setWhether(flowInfo.getWhether());
            response.setFlowStatus(flowInfo.getFlowStatus());
            response.setUserId(flowInfo.getApplyUser().getId());
            response.setUserName(flowInfo.getApplyUser().getUsername());
            getProjectName(flowInfo, response);
            list.add(response);
        }
        List<FlowBusinessResponse> responses = filterList(request, list);
        return responses;
    }

    public List<FlowBusinessResponse> getFinishList(FlowType type) {
        BooleanBuilder builder = new BooleanBuilder();
        QFlowInfo qFlowInfo = QFlowInfo.flowInfo;
        if (Objects.nonNull(type)) {
            builder.and(qFlowInfo.type.eq(type));
        }
        builder.and(qFlowInfo.flowStatus.eq(FlowStatus.FINSH));
        Iterator<FlowInfo> infoIterator = flowInfoRepository.findAll(builder).iterator();
        List<FlowInfo> flowInfoList = Lists.newArrayList(infoIterator);
        List<FlowBusinessResponse> list = flowInfoList.stream().map(flowInfo -> {
            FlowBusinessResponse response = new FlowBusinessResponse();
            response.setCreateTime(flowInfo.getApplyTime());
            response.setFlowId(flowInfo.getId());
            response.setType(flowInfo.getType());
            response.setWhether(flowInfo.getWhether());
            response.setFlowStatus(flowInfo.getFlowStatus());
            getProjectName(flowInfo, response);
            return response;
        }).collect(Collectors.toList());
        return list;
    }


    /**
     * 根据流程获取项目名称（返回对象值）
     *
     * @param flowInfo
     * @return
     */
    public void getProjectName(FlowInfo flowInfo, FlowBusinessResponse response) {
        if (flowInfo.getType().equals(FlowType.REPORT)) {//报地
            reportInfoRepository.findById(flowInfo.getApplyId()).ifPresent(reportInfo -> {
                response.setName(reportInfo.getName());
                response.setAcreage(reportInfo.getAcreage());
                if (Objects.nonNull(reportInfo.getBusinessLayer())) {
                    response.setLayerId(reportInfo.getBusinessLayer().getId());
                    response.setLayerCode(reportInfo.getBusinessLayer().getLayerCode());
                }
                List<String> regions = new ArrayList<>();
                if (reportInfo.getRegions() != null && !reportInfo.getRegions().isEmpty()) {
                    for (DistrictInfo districtInfo : reportInfo.getRegions()) {
                        regions.add(districtInfo.getId());
                    }
                }
                response.setRegions(regions);
                Iterator<GrantInfo> iterator = grantInfoRepository.findAll(QGrantInfo.grantInfo.reportInfo.id.eq(flowInfo.getApplyId())).iterator();
                BigDecimal total = new BigDecimal(0);
                while (iterator.hasNext()){
                    GrantInfo grantInfo = iterator.next();
                    BigDecimal acreage = equalAreaTransformation(grantInfo.getUnit(),grantInfo.getAcreage());
                    total = total.add(acreage);
                }

                BigDecimal surplus = equalAreaTransformation(reportInfo.getUnit(),reportInfo.getAcreage()).subtract(total);
                response.setSurplusAcreage(surplus);
                return;
            });
        } else if (flowInfo.getType().equals(FlowType.GRANT)) {//批地
            grantInfoRepository.findById(flowInfo.getApplyId()).ifPresent(grantInfo -> {
                response.setName(grantInfo.getName());
                response.setAcreage(grantInfo.getAcreage());
                response.setCode(grantInfo.getCode());
                if (Objects.nonNull(grantInfo.getBusinessLayer())) {
                    response.setLayerId(grantInfo.getBusinessLayer().getId());
                    response.setLayerCode(grantInfo.getBusinessLayer().getLayerCode());
                }
                List<String> regions = new ArrayList<>();
                if (grantInfo.getRegions() != null && !grantInfo.getRegions().isEmpty()) {
                    for (DistrictInfo districtInfo : grantInfo.getRegions()) {
                        regions.add(districtInfo.getId());
                    }
                }
                response.setRegions(regions);
                Iterator<SupplyInfo> iterator = supplyInfoRepository.findAll(QSupplyInfo.supplyInfo.grantInfo.id.eq(flowInfo.getApplyId())).iterator();
                BigDecimal total = new BigDecimal(0);
                while (iterator.hasNext()){
                    SupplyInfo supplyInfo = iterator.next();
                    BigDecimal acreage = equalAreaTransformation(supplyInfo.getUnit(),supplyInfo.getAcreage());
                    total = total.add(acreage);
                }
                BigDecimal surplus = equalAreaTransformation(grantInfo.getUnit(),grantInfo.getAcreage()).subtract(total);
                response.setSurplusAcreage(surplus);
                return;
            });
        } else if (flowInfo.getType().equals(FlowType.EXPROPRIA)) { //征地
            expropriationRepository.findById(flowInfo.getApplyId()).ifPresent(expropriation -> {
                response.setName(expropriation.getName());
                response.setAcreage(expropriation.getAcreage());
                response.setCode(expropriation.getCode());
                if (Objects.nonNull(expropriation.getBusinessLayer())) {
                    response.setLayerId(expropriation.getBusinessLayer().getId());
                    response.setLayerCode(expropriation.getBusinessLayer().getLayerCode());
                }
                List<String> regions = new ArrayList<>();
                if (expropriation.getRegions() != null && !expropriation.getRegions().isEmpty()) {
                    for (DistrictInfo districtInfo : expropriation.getRegions()) {
                        regions.add(districtInfo.getId());
                    }
                }
                response.setRegions(regions);
                return;
            });
        } else if (flowInfo.getType().equals(FlowType.SUPPLY)) { //供地
            supplyInfoRepository.findById(flowInfo.getApplyId()).ifPresent(supplyInfo -> {
                response.setName(supplyInfo.getName());
                response.setAcreage(supplyInfo.getAcreage());
                response.setCode(supplyInfo.getCode());
                if (Objects.nonNull(supplyInfo.getBusinessLayer())) {
                    response.setLayerId(supplyInfo.getBusinessLayer().getId());
                    response.setLayerCode(supplyInfo.getBusinessLayer().getLayerCode());
                }
                List<String> regions = new ArrayList<>();
                if (supplyInfo.getRegions() != null && !supplyInfo.getRegions().isEmpty()) {
                    for (DistrictInfo districtInfo : supplyInfo.getRegions()) {
                        regions.add(districtInfo.getId());
                    }
                }
                response.setRegions(regions);
                return;
            });
        } else { //其他类型的项目
            restsInfoRepository.findById(flowInfo.getApplyId()).ifPresent(restsInfo -> {
                response.setName(restsInfo.getName());
                response.setAcreage(restsInfo.getAcreage());
                response.setCode(restsInfo.getCode());
                if (Objects.nonNull(restsInfo.getBusinessLayer())) {
                    response.setLayerId(restsInfo.getBusinessLayer().getId());
                    response.setLayerCode(restsInfo.getBusinessLayer().getLayerCode());
                }
                List<String> regions = new ArrayList<>();
                if (restsInfo.getRegions() != null && !restsInfo.getRegions().isEmpty()) {
                    for (DistrictInfo districtInfo : restsInfo.getRegions()) {
                        regions.add(districtInfo.getId());
                    }
                }
                response.setRegions(regions);
                return;
            });
        }
    }

    /**
     * 查询新建和待审批的审批流程
     *
     * @return
     */
    public List<FlowInfo> getFlowBusinessPending(FlowBusinessRequest request, SessionModel sessionModel) {
        BooleanBuilder builder = new BooleanBuilder();
        QFlowInfo qFlowInfo = QFlowInfo.flowInfo;
        List<FlowInfo> list = new ArrayList<>();
        if (Objects.nonNull(request.getType())) {
            builder.and(qFlowInfo.type.eq(request.getType()));
        }
        if (request.getStatus().equals(FlowStatus.FOUND)) { //流程创建
            builder.and(qFlowInfo.applyUser.id.eq(sessionModel.getId()));
            builder.and(qFlowInfo.flowStatus.eq(FlowStatus.FOUND));
            Iterator<FlowInfo> infoIterator = flowInfoRepository.findAll(builder).iterator();
            list.addAll(Lists.newArrayList(infoIterator));
        } else {//待审批
            builder.and(qFlowInfo.nextUser.id.eq(sessionModel.getId()));
            builder.and(qFlowInfo.flowStatus.in(FlowStatus.FOUND, FlowStatus.PENDING_APPROVAL));
            Iterator<FlowInfo> infoIterator = flowInfoRepository.findAll(builder).iterator();
            list.addAll(Lists.newArrayList(infoIterator));

            BooleanBuilder booleanBuilder = new BooleanBuilder();
            if (Objects.nonNull(request.getType())) {
                booleanBuilder.and(qFlowInfo.type.eq(request.getType()));
            }
            booleanBuilder.and(qFlowInfo.applyUser.id.eq(sessionModel.getId()));
            booleanBuilder.and(qFlowInfo.flowStatus.in(FlowStatus.COMPLETE_APPROVAL));
            Iterator<FlowInfo> iterator = flowInfoRepository.findAll(booleanBuilder).iterator();
            list.addAll(Lists.newArrayList(iterator));
        }
        return list;
    }

    /**
     * 获取当前登录人名下已审批、流程结束、打回
     *
     * @param request
     * @param sessionModel
     * @return
     */
    public List<FlowInfo> getFlowBusinessFinish(FlowBusinessRequest request, SessionModel sessionModel) {
        List<FlowInfo> list = new ArrayList<>();
        BooleanBuilder builder = new BooleanBuilder();
        QFlowInfo qFlowInfo = QFlowInfo.flowInfo;
        Iterator<FlowHistory> iterator = flowHistoryRepository.findAll(QFlowHistory.flowHistory.user.id.eq(sessionModel.getId())).iterator();
        List<String> flowIds = Lists.newArrayList(iterator).stream().map(e -> e.getFlowId()).collect(Collectors.toList());
        builder.and(qFlowInfo.id.in(flowIds));
        if (request.getStatus().equals(FlowStatus.COMPLETE_APPROVAL)) { //已审批
            builder.and(qFlowInfo.applyUser.id.ne(sessionModel.getId()));
            builder.and(qFlowInfo.flowStatus.eq(FlowStatus.COMPLETE_APPROVAL));

            BooleanBuilder booleanBuilder = new BooleanBuilder();
            booleanBuilder.and(qFlowInfo.id.in(flowIds));
            booleanBuilder.and(qFlowInfo.applyUser.id.eq(sessionModel.getId()));
            booleanBuilder.and(qFlowInfo.flowStatus.eq(FlowStatus.PENDING_APPROVAL));
            Iterator<FlowInfo> infoIterator = flowInfoRepository.findAll(booleanBuilder).iterator();
            list.addAll(Lists.newArrayList(infoIterator));
        } else if (request.getStatus().equals(FlowStatus.REPULSE)) { //打回
            builder.and(qFlowInfo.applyUser.id.eq(sessionModel.getId()));
            builder.and(qFlowInfo.flowStatus.eq(FlowStatus.REPULSE));
        }
        if (Objects.nonNull(request.getType())) {
            builder.and(qFlowInfo.type.eq(request.getType()));
        }
        Iterator<FlowInfo> flowInfoIterator = flowInfoRepository.findAll(builder).iterator();
        list.addAll(Lists.newArrayList(flowInfoIterator));
        return list;
    }


    /**
     * 根据流程id查询对应的业务数据
     *
     * @param flowId
     * @return
     */
    public List<UploadFile> getBusinessFileByFlowId(String flowId) {
        List<UploadFile> list = new ArrayList<>();
        flowInfoRepository.findById(flowId).ifPresent(flowInfo -> {
            list.addAll(getUploadFileByFlowInfo(flowInfo));
            return;
        });
        return list;
    }

    /**
     * 根据流程获取项目名称（返回对象值）
     *
     * @param flowInfo
     * @return
     */
    public List<UploadFile> getUploadFileByFlowInfo(FlowInfo flowInfo) {
        List<UploadFile> list = new ArrayList<>();
        List<String> fileIds = new ArrayList<>();
        if (flowInfo.getType().equals(FlowType.REPORT)) {//报地
            reportInfoRepository.findById(flowInfo.getApplyId()).ifPresent(reportInfo -> {
                Iterator<ReportFile> iterator = reportFileRepository.findAll(QReportFile.reportFile.reportId.eq(reportInfo.getId())).iterator();
                List<String> ids = Lists.newArrayList(iterator).stream().map(e -> e.getFileId()).collect(Collectors.toList());
                fileIds.addAll(ids);
                return;
            });
        } else if (flowInfo.getType().equals(FlowType.GRANT)) {//批地
            grantInfoRepository.findById(flowInfo.getApplyId()).ifPresent(grantInfo -> {
                Iterator<GrantFile> iterator = grantFileRepository.findAll(QGrantFile.grantFile.grantId.eq(grantInfo.getId())).iterator();
                List<String> ids = Lists.newArrayList(iterator).stream().map(e -> e.getFileId()).collect(Collectors.toList());
                fileIds.addAll(ids);
                return;
            });
        } else if (flowInfo.getType().equals(FlowType.EXPROPRIA)) { //征地
            expropriationRepository.findById(flowInfo.getApplyId()).ifPresent(expropriation -> {
                Iterator<ExpropriationFile> iterator = expropriationFileRepository.findAll(QExpropriationFile.expropriationFile.expId.eq(expropriation.getId())).iterator();
                List<String> ids = Lists.newArrayList(iterator).stream().map(e -> e.getFileId()).collect(Collectors.toList());
                fileIds.addAll(ids);
                return;
            });
        } else if (flowInfo.getType().equals(FlowType.SUPPLY)) { //工地
            supplyInfoRepository.findById(flowInfo.getApplyId()).ifPresent(supplyInfo -> {
                Iterator<SupplyFile> iterator = supplyFileRepository.findAll(QSupplyFile.supplyFile.supplyId.eq(supplyInfo.getId())).iterator();
                List<String> ids = Lists.newArrayList(iterator).stream().map(e -> e.getFileId()).collect(Collectors.toList());
                fileIds.addAll(ids);
                return;
            });
        } else { //其他项目
            restsInfoRepository.findById(flowInfo.getApplyId()).ifPresent(restsInfo -> {
                Iterator<RestsFile> iterator = restsFileRepository.findAll(QRestsFile.restsFile.restsId.eq(restsInfo.getId())).iterator();
                List<String> ids = Lists.newArrayList(iterator).stream().map(e -> e.getFileId()).collect(Collectors.toList());
                fileIds.addAll(ids);
            });
        }
        Iterator<UploadFile> fileIterator = uploadFileRepository.findAll(QUploadFile.uploadFile.id.in(fileIds)).iterator();
        list.addAll(Lists.newArrayList(fileIterator));
        return list;
    }

    /**
     * 根据流程id查询图层信息
     *
     * @param flowId
     * @return
     */

    public LayerInfoResponse getLayerInfoResponse(String flowId) {
        Optional<LayerInfoResponse> layerInfoResponse = Optional.empty();
        FlowInfo flowInfo = flowInfoRepository.findById(flowId).orElseThrow(() -> new BadRequestException("", "flow.is.not.exist"));

        switch (flowInfo.getType()) {
            case GRANT:
                layerInfoResponse = grantInfoRepository.findById(flowInfo.getApplyId()).map(l -> {
                    if (Objects.nonNull(l.getBusinessLayer())) {
                        LayerInfoResponse lir = new LayerInfoResponse();

                        BeanUtils.copyPropertiesIgnoreNull(l.getBusinessLayer(), lir);
                        return lir;
                    }
                    return null;
                });
                break;
            case REPORT:
                layerInfoResponse = reportInfoRepository.findById(flowInfo.getApplyId()).map(l -> {
                    if (Objects.nonNull(l.getBusinessLayer())) {
                        LayerInfoResponse lir = new LayerInfoResponse();

                        BeanUtils.copyPropertiesIgnoreNull(l.getBusinessLayer(), lir);
                        return lir;
                    }
                    return null;
                });
                break;
            case EXPROPRIA:
                layerInfoResponse = expropriationRepository.findById(flowInfo.getApplyId()).map(l -> {
                    if (Objects.nonNull(l.getBusinessLayer())) {
                        LayerInfoResponse lir = new LayerInfoResponse();

                        BeanUtils.copyPropertiesIgnoreNull(l.getBusinessLayer(), lir);
                        return lir;
                    }
                    return null;
                });
                break;
            case SUPPLY:
                layerInfoResponse = supplyInfoRepository.findById(flowInfo.getApplyId()).map(l -> {
                    if (Objects.nonNull(l.getBusinessLayer())) {
                        LayerInfoResponse lir = new LayerInfoResponse();
                        BeanUtils.copyPropertiesIgnoreNull(l.getBusinessLayer(), lir);
                        return lir;
                    }
                    return null;
                });
                break;
            case RESTS:
                layerInfoResponse = restsInfoRepository.findById(flowInfo.getApplyId()).map(l -> {
                    if (Objects.nonNull(l.getBusinessLayer())) {
                        LayerInfoResponse lir = new LayerInfoResponse();
                        BeanUtils.copyPropertiesIgnoreNull(l.getBusinessLayer(), lir);
                        return lir;
                    }
                    return null;
                });
                break;
        }

        if (layerInfoResponse.isPresent()) {
            return layerInfoResponse.get();
        }
        return null;
    }


    public String getRegions(Set<DistrictInfo> set) {
        String regions = new String();
        if (set != null && !set.isEmpty()) {
            for (DistrictInfo districtInfo : set) {
                regions = regions.concat(districtInfo.getId()).concat(",");
            }
            regions = regions.substring(0, regions.length() - 1);
        }
        return regions;
    }
    /**
     * 根据流程id查询对应的基础信息
     *
     * @param flowId
     * @return
     */
    public BusinessInfoResponse getBusinessInfoResponseByFlowId(String flowId) {
        BusinessInfoResponse response = new BusinessInfoResponse();
        flowInfoRepository.findById(flowId).ifPresent(flowInfo -> {
            response.setType(flowInfo.getType().toString());
            if (flowInfo.getType().equals(FlowType.REPORT)) {//报地
                reportInfoRepository.findById(flowInfo.getApplyId()).ifPresent(reportInfo -> {
                    BeanUtils.copyPropertiesIgnoreNull(reportInfo, response);
                    response.setReportId(reportInfo.getId());
                    response.setReportName(reportInfo.getName());
                    response.setRegions(getRegions(reportInfo.getRegions()));
                    return;
                });
            } else if (flowInfo.getType().equals(FlowType.GRANT)) {//批地
                grantInfoRepository.findById(flowInfo.getApplyId()).ifPresent(grantInfo -> {
                    BeanUtils.copyPropertiesIgnoreNull(grantInfo, response);
                    response.setGrantId(grantInfo.getId());
                    response.setGrantName(grantInfo.getName());
                    response.setGrantCode(grantInfo.getCode());
                    response.setRegions(getRegions(grantInfo.getRegions()));
                    if (Objects.nonNull(grantInfo.getReportInfo())) {
                        response.setReportId(grantInfo.getReportInfo().getId());
                        response.setReportName(grantInfo.getReportInfo().getName());
                    }
                    return;
                });
            } else if (flowInfo.getType().equals(FlowType.EXPROPRIA)) { //征地
                expropriationRepository.findById(flowInfo.getApplyId()).ifPresent(expropriation -> {
                    BeanUtils.copyPropertiesIgnoreNull(expropriation, response);
                    response.setExpropriationName(expropriation.getName());
                    response.setExpropriationCode(expropriation.getCode());
                    response.setRegions(getRegions(expropriation.getRegions()));
                    if (Objects.nonNull(expropriation.getGrantInfo())) {
                        response.setGrantId(expropriation.getGrantInfo().getId());
                        response.setGrantCode(expropriation.getGrantInfo().getCode());
                        response.setGrantName(expropriation.getGrantInfo().getName());
                        response.setGrantTime(expropriation.getGrantInfo().getGrantTime());
                        response.setGrantRemark(expropriation.getGrantInfo().getGrantRemark());
                        if (Objects.nonNull(expropriation.getGrantInfo().getReportInfo())) {
                            response.setReportId(expropriation.getGrantInfo().getReportInfo().getId());
                            response.setReportName(expropriation.getGrantInfo().getReportInfo().getName());
                        }
                    }
                    return;
                });
            } else if (flowInfo.getType().equals(FlowType.SUPPLY)) { //工地
                supplyInfoRepository.findById(flowInfo.getApplyId()).ifPresent(supplyInfo -> {
                    BeanUtils.copyPropertiesIgnoreNull(supplyInfo, response);
                    response.setSupplyName(supplyInfo.getName());
                    response.setSupplyCode(supplyInfo.getCode());
                    response.setRegions(getRegions(supplyInfo.getRegions()));
                    if (Objects.nonNull(supplyInfo.getGrantInfo())) {
                        response.setGrantId(supplyInfo.getGrantInfo().getId());
                        response.setGrantCode(supplyInfo.getGrantInfo().getCode());
                        response.setGrantName(supplyInfo.getGrantInfo().getName());
                        response.setGrantTime(supplyInfo.getGrantInfo().getGrantTime());
                        response.setGrantRemark(supplyInfo.getGrantInfo().getGrantRemark());
                        if (Objects.nonNull(supplyInfo.getGrantInfo().getReportInfo())) {
                            response.setReportId(supplyInfo.getGrantInfo().getReportInfo().getId());
                            response.setReportName(supplyInfo.getGrantInfo().getReportInfo().getName());
                        }
                    }
                    return;
                });
            } else { //其他项目类型
                restsInfoRepository.findById(flowInfo.getApplyId()).ifPresent(restsInfo -> {
                    BeanUtils.copyPropertiesIgnoreNull(restsInfo, response);
                    return;
                });
            }
            return;
        });
        return response;
    }


    /**
     * 获取当前用户的新建、已审批、待审批、打回流程数量
     *
     * @param sessionModel
     * @return
     */
    public FlowNumberResponse getFlowNumberResponse(SessionModel sessionModel) {
        FlowNumberResponse response = new FlowNumberResponse();
        QFlowInfo qFlowInfo = QFlowInfo.flowInfo;
        BooleanBuilder foundBuild = new BooleanBuilder();
        foundBuild.and(qFlowInfo.flowStatus.eq(FlowStatus.FOUND));
        foundBuild.and(qFlowInfo.applyUser.id.eq(sessionModel.getId()));
        Long found = flowInfoRepository.count(foundBuild);
        response.setFound(found.intValue());//新建数量

        BooleanBuilder pendingBuild = new BooleanBuilder();
        pendingBuild.and(qFlowInfo.flowStatus.eq(FlowStatus.PENDING_APPROVAL));
        pendingBuild.and(qFlowInfo.nextUser.id.eq(sessionModel.getId()));
        Long pending = flowInfoRepository.count(pendingBuild);
        response.setPending(pending.intValue());//待审批

        BooleanBuilder repulseBuild = new BooleanBuilder();
        repulseBuild.and(qFlowInfo.flowStatus.eq(FlowStatus.REPULSE));
        repulseBuild.and(qFlowInfo.applyUser.id.eq(sessionModel.getId()));
        Long repulse = flowInfoRepository.count(pendingBuild);
        response.setRepulse(repulse.intValue());//打回

        BooleanBuilder builder = new BooleanBuilder();
        QFlowHistory qFlowHistory = QFlowHistory.flowHistory;
        builder.and(qFlowHistory.user.id.eq(sessionModel.getId()));
        Long complete = flowHistoryRepository.count(builder);
        response.setComplete(complete.intValue() - found.intValue());
        return response;
    }


    /**
     * 根据业务id判断该业务流程是否是拒绝状态
     *
     * @param applyId
     * @return
     */
    public boolean exitRefuse(String applyId) {
        BooleanBuilder builder = new BooleanBuilder();
        QFlowInfo qFlowInfo = QFlowInfo.flowInfo;
        builder.and(qFlowInfo.applyId.eq(applyId));
        builder.and(qFlowInfo.flowStatus.eq(FlowStatus.FINSH));
        Iterator<FlowInfo> iterator = flowInfoRepository.findAll(builder).iterator();
        while (iterator.hasNext()) {
            FlowInfo flowInfo = iterator.next();
            Iterator<FlowHistory> flowHistoryIterator = flowHistoryRepository.findAll(QFlowHistory
                    .flowHistory.flowId.eq(flowInfo.getId())).iterator();
            while (flowHistoryIterator.hasNext()) {
                FlowHistory flowHistory = flowHistoryIterator.next();
                if (flowHistory.getStatus().equals(FlowResultStatus.REFUSE)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 根据id查询对应的供地信息
     * @param id
     */
    public SupplyInfoResponse querySupplyInfoById(String id){
        SupplyInfoResponse response = new SupplyInfoResponse();
        BooleanBuilder builder = new BooleanBuilder();
        QSupplyInfo qSupplyInfo = QSupplyInfo.supplyInfo;
        builder.and(qSupplyInfo.grantInfo.id.eq(id));
        Iterable<SupplyInfo> iterable = supplyInfoRepository.findAll(builder);
        List<SupplyInfo> supplyInfos = Lists.newArrayList(iterable);
        response.setSupplyInfos(supplyInfos);
        BigDecimal acreage = new BigDecimal(0);
        for (SupplyInfo supplyInfo : supplyInfos){
            BigDecimal total = equalAreaTransformation(supplyInfo.getUnit(),supplyInfo.getAcreage());
            acreage = acreage.add(total);
        }

        Optional<GrantInfo> optional = grantInfoRepository.findById(id);
        if(optional.isPresent()){
            GrantInfo grantInfo = optional.get();
            BigDecimal surplus = equalAreaTransformation(grantInfo.getUnit(),grantInfo.getAcreage()).subtract(acreage);
            response.setAcreage(surplus);
        }
        return response;
    }

    /**
     * 面积转换
     * @return
     */
    public BigDecimal equalAreaTransformation(AreaUnit areaUnit,BigDecimal acreage){
        BigDecimal result = new BigDecimal(0);
        switch (areaUnit){
            case SQUARE_METRE:
                result = acreage;
                break;
            case MU:
                result = acreage.multiply(new BigDecimal(666.6666667));
                break;
            case HECTARE:
                result = acreage.multiply(new BigDecimal(10000));
                break;
            default:
                break;
        }
        return result;
    }
}
